Adopt two-phase CI/CD with PR smoke builds and opt-in publish - #98
Merged
Conversation
Decouple merging from publishing (issue #97). By default, PRs run path-gated smoke builds (Docker amd64-only, reduced executable matrix, no push) and merges to main/develop no longer publish; the weekly schedule and manual dispatch are the sole publishers, building and releasing both branches in one run via a branch matrix. Set the PUBLISH_ON_MERGE repository variable to true to opt back into legacy publish-on-every-merge. Thread ref/branch/smoke through every reusable build task so branch- derived config keys off inputs.branch (not github.ref_name), letting a scheduled run version and build develop as well as main. Add per-target enable gates and a paths-filter changes job for fast, modular PR feedback; the required status aggregator now fails if path detection fails so a target-changing PR cannot merge with its smoke build skipped. Branch-suffix build artifacts and branch-scope the Docker registry cache so the two matrix legs do not collide or overwrite each other's cache. Move codegen from weekly to daily, fold unit tests into the PR workflow, and remove the now-redundant test-release-task and publish-periodic-docker-release workflows. Correct the Copilot review runbook: the requestReviews GraphQL mutation now reliably re-requests a review (previously needed a manual UI click), and make the wait-for-maintainer-merge gate explicit.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR restructures the template’s CI/CD into a two-phase model: pull requests run fast, path-gated smoke builds, while publishing is batched into a scheduled/manual workflow with an opt-in “publish on merge” switch.
Changes:
- Replaces the PR validation workflow with unit tests + path-gated smoke builds of only the affected delivery targets.
- Refactors publishing so
publish-release.ymlbecomes the central publisher (weekly + manual), with push-triggered publishing gated byPUBLISH_ON_MERGE. - Threads
ref/branch/smokethrough reusable build workflows to support a branch matrix (publishingmainanddevelopin one run) and avoid artifact/cache collisions.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates documentation to describe the new two-phase model and codegen schedule. |
| ProjectTemplate.slnx | Removes deleted workflow files from solution items. |
| AGENTS.md | Adds authoritative “Release Model” section and updates review-loop guidance. |
| .github/workflows/test-release-task.yml | Removes the prior “test release” reusable workflow. |
| .github/workflows/test-pull-request.yml | Implements PR path detection + smoke build orchestration + hardened required-check aggregator. |
| .github/workflows/run-periodic-codegen-pull-request.yml | Changes codegen schedule from weekly to daily and updates rationale comments. |
| .github/workflows/publish-release.yml | Introduces publish planning + branch matrix; gates push publishing via PUBLISH_ON_MERGE; adds weekly schedule; changes concurrency cancellation behavior. |
| .github/workflows/publish-periodic-docker-release.yml | Removes the old periodic Docker-only publisher workflow. |
| .github/workflows/get-version-task.yml | Adds ref input to versioning task to support matrix publishing. |
| .github/workflows/build-release-task.yml | Adds ref/branch/smoke + per-target gates; forwards parameters to leaf build tasks; adjusts GitHub release tagging logic. |
| .github/workflows/build-pypilibrary-task.yml | Adds ref/branch; branches artifact names; switches version logic to use inputs.branch. |
| .github/workflows/build-nugetlibrary-task.yml | Adds ref/branch; branches artifact names; uses inputs.branch for config selection. |
| .github/workflows/build-executable-task.yml | Adds ref/branch/smoke; reduces runtime matrix under smoke; branches artifact names; skips aggregation under smoke. |
| .github/workflows/build-docker-task.yml | Adds ref/branch/smoke; makes smoke amd64-only; introduces branch-scoped registry cache. |
| .github/workflows/build-datebadge-task.yml | Adds branch input and gates badge write by inputs.branch. |
| .github/copilot-instructions.md | Updates the Copilot runbook to document GraphQL requestReviews re-request flow. |
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
.github/workflows/build-docker-task.yml:69
- The Docker Hub login step always runs, which will fail on forked PR smoke builds (secrets are unavailable) even though
pushis false. Gate the login oninputs.pushso PR smoke builds can still compile Docker images anonymously, while publish runs authenticate.
- name: Setup Buildx step
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
with:
platforms: ${{ inputs.smoke && 'linux/amd64' || 'linux/amd64,linux/arm64' }}
# Always login to Docker Hub, not just on push, to benefit from
# higher rate limits with a Docker subscription for pulls and cache
- name: Login to Docker Hub step
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
.github/workflows/build-docker-task.yml:68
docker/login-actionruns unconditionally, so PR smoke builds (and any non-publishing builds where secrets aren’t available, e.g. fork PRs / Dependabot runs without Docker Hub secrets) can fail before they even reach the build. Sincepush=falsesmoke builds are explicitly meant to work without registry credentials, gate the login step on eitherinputs.pushor the presence of the Docker Hub secrets.
platforms: ${{ inputs.smoke && 'linux/amd64' || 'linux/amd64,linux/arm64' }}
# Always login to Docker Hub, not just on push, to benefit from
# higher rate limits with a Docker subscription for pulls and cache
- name: Login to Docker Hub step
This was referenced Jun 3, 2026
ptr727
added a commit
that referenced
this pull request
Jun 4, 2026
Release merge of `develop` into `main`. ## Headline change (#98, closes #97) Two-phase CI/CD that decouples merging from publishing across all four delivery targets (Docker, NuGet, PyPI, console executable): - **PRs smoke-test only** — path-gated, reduced builds (Docker `linux/amd64`, trimmed executable matrix), no publish. - **Sole publisher** — `publish-release.yml` (weekly schedule + manual dispatch) builds/publishes **both** branches via a matrix; the `push` trigger publishes only when the **`PUBLISH_ON_MERGE`** repository variable is `true` (opt-in legacy continuous-release). Default is two-phase. - Parameterized chain (`ref`/`branch`/`smoke`, per-target `enable_*` gates), branch-suffixed artifacts, branch-scoped Docker cache, hardened required-status aggregator. - Robustness: skip GitHub release on a duplicate version (no-op weeks), pin the release tag to NBGV `GitCommitId`, global publish concurrency, `cache-to`/login gating reviewed. - CodeGen weekly → daily; `test-release-task.yml` + `publish-periodic-docker-release.yml` removed. - Corrected the Copilot review runbook (reliable `requestReviews` mutation) and made the wait-for-maintainer-merge gate explicit. Also includes routine codegen updates (#93, #95). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ptr727
added a commit
to ptr727/NxWitness
that referenced
this pull request
Jun 4, 2026
Closes #407. Two robustness fixes to the `github-release` job in `publish-release.yml`, ported from ptr727/ProjectTemplate#98. ## 1. Skip duplicate release on no-op weeks The weekly schedule re-runs even when `main` has no new commits, so NBGV produces the **same `SemVer2`** and `softprops/action-gh-release` is asked to (re)create an existing release/tag — churning the release every week and risking failures re-uploading existing assets. Added a `Check for existing release` step (`gh release view "$SemVer2"`) that gates the release-creation step, so a no-op week is a true no-op. ## 2. Pin release tag to the built commit, not a moving ref `target_commitish: main` is a **moving ref** — a commit landing on `main` mid-run could tag the release on a newer commit than the one built. Pinned it to NBGV's `GitCommitId` (the exact commit the version was computed from; `get-version` runs with `ref: main`). Added `GitCommitId` as a `get-version-task.yml` output. Matches the existing file conventions (no new action pins introduced). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ptr727
added a commit
to ptr727/NxWitness
that referenced
this pull request
Jun 4, 2026
Release merge of `develop` into `main`. ## Changes - **Release-job robustness** (#408, closes #407): skip GitHub release creation on no-op weekly runs (when the `SemVer2` tag already exists), while still allowing `workflow_dispatch` to repair a release; and pin `target_commitish` + the release-job checkout to NBGV `GitCommitId` (the exact built commit) instead of the moving `main` ref. Ported from ptr727/ProjectTemplate#98. - Dependabot: bump `dorny/paths-filter` 3 → 4 (#409). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #97.
What
Decouple merging from publishing across all four delivery targets (Docker, NuGet, PyPI, console executable).
linux/amd64only, reduced executable matrix, no push). Merges tomain/developno longer publish.publish-release.yml(weekly schedule + manual dispatch) builds and publishes both branches in one run via a branch matrix; itspushtrigger publishes only when thePUBLISH_ON_MERGErepository variable istrue(opt-in legacy continuous-release).ref/branch/smokeare threaded through every reusable task; branch-derived config keys offinputs.branch, nevergithub.ref_name, so a scheduled run can version/builddevelopas well asmain.get-version-task.ymlgained arefinput.buildcache-main/buildcache-develop, reads both, writes own) so the two legs never collide or overwrite each other's cache.test-release-task.ymlandpublish-periodic-docker-release.ymlremoved.enable_*gates so a derived project can drop a target with minimal edits (checklist in AGENTS.md).Copilot runbook
Corrects
.github/copilot-instructions.md: therequestReviewsGraphQL mutation now reliably re-requests a review (previously documented as non-working / manual-UI-only), and the wait-for-maintainer-merge gate is now explicit in AGENTS.md.Notes
.NETNuGet restore caching is intentionally left off (low overhead, no lock files under Central Package Management) — documented inline.🤖 Generated with Claude Code